package com.ruoqing.auth.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.concurrent.TimeUnit;

/**
	* @author YaoXian
	* @title: AuthorizationServerConfiguration
	* @projectName ruoxi-blog
	* @description: 若兮微服务 - 认证授权中心 - 认证服务器配置类
	* @date 2020-11-25 18:25
	*/

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
		
		@Resource
		private AuthenticationManager authenticationManager;
		
		@Resource
		private TokenStore tokenStore;
		
		
		@Bean
		@Primary
		@ConfigurationProperties(prefix = "spring.datasource")
		public DataSource dataSource() {
				// 配置数据源（注意，我使用的是 HikariCP 连接池），以上注解是指定数据源，否则会有冲突
				return DataSourceBuilder.create().build();
		}
		
		@Bean
		public TokenStore tokenStore() {
				// 基于 JDBC 实现，令牌保存到数据
				return new JdbcTokenStore(dataSource());
		}
		
		@Bean
		public ClientDetailsService jdbcClientDetails() {
				// 基于 JDBC 实现，需要事先在数据库配置客户端信息
				return new JdbcClientDetailsService(dataSource());
		}
		
		/**
			*
			* @param endpoints
			*/
		@Override
		public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
				// 设置令牌
				endpoints.authenticationManager(authenticationManager);
				endpoints.tokenStore(tokenStore());
				//配置TokenServices参数
				DefaultTokenServices tokenServices = new DefaultTokenServices();
				tokenServices.setTokenStore(endpoints.getTokenStore());
				tokenServices.setSupportRefreshToken(true);
				tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
				tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
				// 1天
				tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(1));
				endpoints.tokenServices(tokenServices);
		}
		
		/**
			*
			* @return
			*/
		@Bean
		@Primary
		public DefaultTokenServices tokenServices() {
				DefaultTokenServices tokenServices = new DefaultTokenServices();
				tokenServices.setSupportRefreshToken(true);
				tokenServices.setTokenStore(tokenStore);
				return tokenServices;
		}
		
		@Override
		public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
				oauthServer
								.tokenKeyAccess("permitAll()")
								.checkTokenAccess("permitAll()")
								.allowFormAuthenticationForClients();
				
					oauthServer.allowFormAuthenticationForClients();
		}
		
		@Override
		public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
				// 读取客户端配置
				clients.withClientDetails(jdbcClientDetails());
		}
}
